<template>
  <div ref="ganttRef"></div>
</template>

<script setup lang="ts">
import { onMounted, ref, watch } from 'vue'
import { gantt } from 'king7-gantt' // 引入dhtmlx-gantt

const props = withDefaults(defineProps<{
  tasks: any,
  columns: any,
  scaleUnit?: any,
  dateScale?: any,
  fullScreen: boolean
}>(), {
  tasks: {
    data: [], // 数据数组
    links: [] // 连接关系
  },
  columns: () => [],
  scaleUnit: 'day',
  dateScale: '%Y-%m-%d',
  fullScreen: false
})
// 挂载ref
const ganttRef = ref()
onMounted(() => {
  // 清空之前的配置
  gantt.clearAll()
  // 默认配置
  gantt.config.xml_date = '%Y-%m-%d' // 日期格式化的匹配格式
  gantt.config.scale_height = 90; // 日期栏的高度
  gantt.i18n.setLocale('cn') // 设置中文
  // gantt.config.readonly = true // 设置为只读
  // 显示列配置
  gantt.config.columns = props.columns
  // gantt.config.scale_unit = props.scaleUnit
  // gantt.config.date_scale = props.dateScale
  gantt.config.scales = [
    // { unit: "month", step: 1, format: "%F, %Y" },
    // { unit: "day", step: 1, format: "%j, %D" }
    { unit: "year", step: 1, format: "%Y" }, // F月份
    {
      unit: "quarter", step: 1, format: function (date) {
        let dateToStr = gantt.date.date_to_str("%n");
        let quarterNum = 0
        let quarter = '1月 - 3月'
        if (dateToStr(date) < 4) {
          quarterNum = 1
          quarter = '1月 - 3月'
        } else if (3 < dateToStr(date) && dateToStr(date) < 7) {
          quarterNum = 2
          quarter = '4月 - 6月'
        } if (6 < dateToStr(date) && dateToStr(date) < 10) {
          quarterNum = 3
          quarter = '7月 - 9月'
        } else {
          quarterNum = 4
          quarter = '10月 - 12月'
        }
        return "季度 #" + quarterNum + ", " + quarter
      }
    }, // F月份
    { unit: "month", step: 1, format: "%M" }, // F月份，j日期，D星期
    {
      unit: "week", step: 1, format: function (date) {
        let dateToStr = gantt.date.date_to_str("%d %M");
        let endDate = gantt.date.add(date, -1, "day");
        let startDate = gantt.date.add(date, -7, "day");
        let weekNum = gantt.date.date_to_str("%W")(date);
        return "Week #" + weekNum + ", " + dateToStr(startDate) + " - " + dateToStr(endDate);
      }
    },
    { unit: "day", step: 1, format: "%j, %D" }
  ];
  gantt.config.min_column_width = 80;
  let zoomConfig: any = {
    // minColumnWidth: 80,
    // maxColumnWidth: 150,
    levels: [
      {
        name: "day",
        scale_height: 50,
        min_column_width: 80,
        scales: [
          { unit: "year", step: 1, format: "%Y" },
          { unit: "month", format: "%M", step: 1 },
          { unit: "day", format: "%d", step: 1 },
        ]
      },
      {
        name: "week",
        scale_height: 50,
        min_column_width: 50,
        scales: [
          { unit: "year", step: 1, format: "%Y" },
          { unit: "month", format: "%M", step: 1 },
          {
            unit: "week", step: 1, format: function (date: any) {
              let dateToStr = gantt.date.date_to_str("%d %M");
              let endDate = gantt.date.add(date, -1, "day");
              let startDate = gantt.date.add(date, -7, "day");
              let weekNum = gantt.date.date_to_str("%W")(date);
              return "Week #" + weekNum + ", " + dateToStr(startDate) + " - " + dateToStr(endDate);
            }
          },
        ]
      },
      {
        name: "month",
        scale_height: 50,
        min_column_width: 120,
        scales: [
          { unit: "year", step: 1, format: "%Y" },
          { unit: "month", format: "%M", step: 1 },
        ]
      },
      {
        name: "quarter",
        scale_height: 50,
        min_column_width: 80,
        scales: [
          { unit: "year", step: 1, format: "%Y" },
          {
            unit: "quarter", step: 1, format: function (date: any) {
              let dateToStr = gantt.date.date_to_str("%M");
              let dateToStrNum = gantt.date.date_to_str("%n");
              let endDate = gantt.date.add(gantt.date.add(date, 3, "month"), -1, "day");
              let quarterNum = 0
              if (dateToStrNum(date) < 4) {
                quarterNum = 1
              } else if (3 < dateToStrNum(date) && dateToStrNum(date) < 7) {
                quarterNum = 2
              } if (6 < dateToStrNum(date) && dateToStrNum(date) < 10) {
                quarterNum = 3
              } else {
                quarterNum = 4
              }
              return "季度 #" + quarterNum + ", " + dateToStr(date) + " - " + dateToStr(endDate);
            }
          }
        ]
      },
      {
        name: "year",
        scale_height: 50,
        min_column_width: 30,
        scales: [
          { unit: "year", step: 1, format: "%Y" },
        ]
      },
    ],
    // startDate: new Date('2023-01-01'),
    // endDate: new Date('2023-12-31'),
    useKey: "ctrlKey",
    trigger: "wheel",
    element: function () {
      return gantt.$root.querySelector(".gantt_task");
    }
  }
  gantt.ext.zoom.init(zoomConfig)
  gantt.templates.rightside_text = function (start, end, task) {
    if (task.type == "milestone") {
      return task.text;
    }
    return "";
  }
  gantt.config.min_grid_column_width = 120; //设置左侧表格各列宽度
  gantt.config.keep_grid_width = false;
  gantt.config.grid_resize = true
  // gantt.config.scale_height = 39;
  // gantt.config.row_height = 40;
  // gantt.config.select_task  = false
  // gantt.config.show_links = true // 禁用连线
  // gantt.config.drag_links = false;
  gantt.config.cascade_delete = false;
  gantt.config.drag_progress = false // 禁用工作进度拖拽
  gantt.config.show_progress = false //
  // 排序
  gantt.config.sort = true
  // 拖拽行
  gantt.config.order_branch = "marker";
  gantt.config.order_branch_free = true
  // 若要防止将任务拖放到特定位置，请改用onBeforeRowDragMove事件（仅在“标记”模式下有效）。
  // gantt.attachEvent("onBeforeRowDragMove", function (id, parent, tindex) {
  //   // return true/false;
  // });
  // tindex： 父分支中任务将移动到的位置的索引
  gantt.attachEvent("onAfterTaskMove", function (id, parent, tindex) {
    // any custom logic here
    console.log(id, parent, tindex);
  });
  // 发生异常时，不允许弹出警告到UI界面
  gantt.config.show_errors = false;
  var secondGridColumns = {
    columns: [
      {
        name: "add", label: "操作", width: 50, align: "center",
      },
    ]
  }
  gantt.config.layout = {
    css: "gantt_container",
    cols: [
      {
        width: 400,
        min_width: 300,
        rows: [
          { view: "grid", scrollX: "gridScroll", scrollable: true, scrollY: "scrollVer" },
          { view: "scrollbar", id: "gridScroll", group: "horizontal" },
        ]
      },
      { view: "grid", width: 50, bind: "task", scrollY: "scrollVer", config: secondGridColumns },
      { resizer: true, width: 1 },
      {
        rows: [
          { view: "timeline", scrollX: "scrollHor", scrollY: "scrollVer" },
          { view: "scrollbar", id: "scrollHor", group: "horizontal" }
        ]
      },
      { view: "scrollbar", id: "scrollVer" }
    ]
  }
  gantt.config.grid_width = 500;
  // 禁用原来自带的弹窗
  gantt.attachEvent(
    'onBeforeLightbox',
    function (id) {
      console.log(1);
      return false; // 返回 false
    },
    {}
  )
  // 禁用双击事件
  gantt.attachEvent(
    'onTaskDblClick',
    function (id, e) {
      console.log('id', id, e);
      // dialogVisible.value = true;
      return false;
    },
    {}
  )
  // 设置最短任务持续时间
  gantt.config.min_duration = 24 * 60 * 60 * 1000 // 1day
  // 自动延长时间刻度
  gantt.config.fit_tasks = true
  gantt.attachEvent("onBeforeLinkDisplay", function (id, link) {
    if (link.type == gantt.config.links.finish_to_start) {
      return true;
    }
    return false;
  });
  // 任务移动后
  gantt.attachEvent("onTaskDrag", function (id, mode, task, original) {
    // console.log(id, mode, task, original);
    let modes = gantt.config.drag_mode;
    // 要在用户拖动其父项的任务时允许拖动子项
    if (mode == modes.move) {
      let diff = task.start_date - original.start_date;
      gantt.eachTask(function (child) {
        child.start_date = new Date(+child.start_date + diff);
        child.end_date = new Date(+child.end_date + diff);
        gantt.refreshTask(child.id, true);
      }, id);
    }
    if (mode == modes.move || mode == modes.resize) {
      let diff = original.duration * (1000 * 60 * 60 * 24)
      // 任务只能在父任务时间内拖动
      gantt.eachParent(function (parent) {
        if (+task.start_date < +parent.start_date) {
          task.start_date = new Date(parent.start_date);
          if (mode == modes.move)
            task.end_date = new Date(+task.start_date + diff);
        }
        if (+task.end_date > +parent.end_date) {
          task.end_date = new Date(parent.end_date);
          if (mode == modes.move)
            task.start_date = new Date(+task.end_date - diff)
        }
      }, id);
    }
  });
  // 要在用户拖动其父项的任务时允许拖动子项
  gantt.attachEvent("onAfterTaskDrag", function (id, mode, e) {
    let modes = gantt.config.drag_mode;
    if (mode == modes.move) {
      let state = gantt.getState();
      gantt.eachTask(function (child) {
        child.start_date = gantt.roundDate({
          date: child.start_date,
          unit: state.scale_unit,
          step: state.scale_step
        });
        child.end_date = gantt.calculateEndDate(child.start_date,
          child.duration, gantt.config.duration_unit);
        gantt.updateTask(child.id);
      }, id);
    }
  });
  gantt.attachEvent("onLinkDblClick", function (id, e) {
    return false
  })
  gantt.attachEvent("onTaskClick", function (id, e) {
    console.log("task click", id, e);
    if (e.target.id === 'my-click') {
      alert('编辑')
      console.log(gantt.getTask(id));
    }
    return true;
  });
  let selected_column: any = null;

  gantt.attachEvent("onScaleClick", function (e, date) {
    selected_column = date;
    let pos = gantt.getScrollState();
    gantt.render();
    gantt.scrollTo(pos.x, pos.y);
  });

  function is_selected_column(column_date: any) {
    if (selected_column && +column_date == +selected_column) {
      return true;
    }
    return false;
  }
  gantt.config.inherit_scale_class = true; // 子坐标轴是否使用 scale_cell_class模版
  gantt.templates.scale_cell_class = function (date) {
    // 突出周末
    // if (date.getDay() == 0 || date.getDay() == 6) {
    //   return "weekend";
    // }
    if (is_selected_column(date))
      return "highlighted-column";
    return ''
  };
  gantt.templates.timeline_cell_class = function (task, date) {
    if (is_selected_column(date))
      return "highlighted-column";
    return ''
  }
  // detachEvent
  // 排序后  direction：true - 下降， false - 上升的
  gantt.attachEvent("onAfterSort", function (field, direction, parent) {
    // your code here
    console.log(field, direction, parent);
  });
  gantt.plugins({
    marker: true,
    fullscreen: true, // 全屏
    tooltip: true
  });
  gantt.templates.tooltip_text = function (start, end, task) {
    return "<b>Task:</b> " + task.text + "<br/><b>开始日期:</b> " +
      gantt.templates.tooltip_date_format(start) +
      "<br/><b>结束日期:</b> " + gantt.templates.tooltip_date_format(end);
  };
  gantt.addMarker({
    start_date: new Date(),
    text: '今日',
    css: "today",
  });
  gantt.addMarker({
    start_date: new Date('2023-08-01'),
    text: '里程碑'
  });
  watch(() => props.fullScreen, () => {
    gantt.ext.fullscreen.toggle()
  })
  // scrollTo 滚动
  // 不选中
  // function unselectTasks() {
  //   gantt.eachSelectedTask(function (item) {
  //     gantt.unselectTask(item.id);
  //   });
  // }
  // Link styles
  // Task styles
  // 初始化甘特图
  gantt.init(ganttRef.value)
  // 渲染数据
  gantt.parse(props.tasks)
  gantt.message({
    text: "使用 <b>ctrl + 滚轮</b> 来缩放时间",
    expire: -1
  });
})
</script>

<style lang="scss">
/* .gantt_grid_scale,
.gantt_task_scale,
.gantt_task_vscroll {
  background-color: #eee;
} */

/* task */

/* background color of task bars*/
.gantt_task_line {
  background-color: #42a5f5;
  border: 1px solid #2898b0;
}

/* text color */
.gantt_task_line .gantt_task_content {
  color: #fff;
}

/* progress fill */
.gantt_task_progress {
  background: #1976d2;
}

/* project */
/* background color of project bars*/
.gantt_task_line.gantt_bar_project {
  background-color: #66bb6a;
  border: 1px solid #3c9445;
}

/* progress of project bars */
.gantt_task_line.gantt_bar_project .gantt_task_progress {
  background-color: #43a047;
}

.highlighted-column {
  background-color: #fff3a1;
}

.gantt_task_scale .gantt_scale_cell {
  cursor: default;
}

.gantt_task_scale .gantt_scale_cell.highlighted-column {
  color: #454545 !important;
  font-weight: bold;
}

.gantt_grid_head_cell .gantt_sort {
  top: 17px;
}
</style>